package com.ncmmall.api.apis.mall;

import com.ncmmall.api.apis.service.Result;
import com.ncmmall.api.params.MerchantShoppingCartGoodsDTO;
import com.ncmmall.api.params.OrderPreviewDTO;
import com.ncmmall.api.params.ShopCartDTO;
import com.ncmmall.api.security.Securitys;
import com.ncmmall.application.business.goods.GoodsApplication;
import com.ncmmall.application.business.member.MemberApplication;
import com.ncmmall.application.business.order.OrderApplication;
import com.ncmmall.application.business.shoppingcart.ShoppingCartApplication;
import com.ncmmall.application.util.HttpRequests;
import com.feijin.commons.exceptions.InterfaceException;
import com.feijin.commons.lang.ArithUtils;
import com.feijin.commons.securitys.MD5HashUtils;
import com.ncmmall.domain.business.deliveryaddress.DeliveryAddress;
import com.ncmmall.domain.business.deliveryaddress.QDeliveryAddress;
import com.ncmmall.domain.business.goods.Goods;
import com.ncmmall.domain.business.goods.sku.GoodsSku;
import com.ncmmall.domain.business.goods.sku.QGoodsSku;
import com.ncmmall.domain.business.goods.unit.GoodsUnit;
import com.ncmmall.domain.business.goods.unit.QGoodsUnit;
import com.ncmmall.domain.business.merchant.freight.MerchantFreight;
import com.ncmmall.domain.business.merchant.freight.MerchantFreightTemplate;
import com.ncmmall.domain.business.merchant.freight.QMerchantFreight;
import com.ncmmall.domain.business.merchant.freight.QMerchantFreightTemplate;
import com.ncmmall.domain.business.order.Order;
import com.ncmmall.domain.business.order.OrderDetail;
import com.ncmmall.domain.business.order.QOrder;
import com.ncmmall.domain.business.order.aftersale.OrderAfterSale;
import com.ncmmall.domain.business.order.aftersale.QOrderAfterSale;
import com.ncmmall.domain.business.order.delivery.QSupplierOrderDelivery;
import com.ncmmall.domain.business.order.delivery.SupplierOrderDelivery;
import com.ncmmall.domain.business.order.dto.OrderDTO;
import com.ncmmall.domain.business.order.dto.SupplierOrderDTO;
import com.ncmmall.domain.business.setting.CancelCause;
import com.ncmmall.domain.business.setting.QCancelCause;
import com.ncmmall.domain.business.shoppingcart.QShoppingCart;
import com.ncmmall.domain.business.shoppingcart.ShoppingCart;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.querychannel.QueryPage;
import com.ncmmall.querychannel.QueryPageRequest;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author linxs
 * @Description: 订单模块相关的API接口
 * @Date: 2019-07-15 17:06
 */
@RestController
@RequestMapping(value = "/order")
@Component
public class OrderApi {

    private final Logger logger = LoggerFactory.getLogger(ShoppingCartApi.class);

    @Autowired
    private QueryChannelService queryChannelService;

    @Autowired
    private ShoppingCartApplication shoppingCartApplication;

    @Autowired
    private GoodsApplication goodsApplication;

    @Autowired
    private OrderApplication orderApplication;

    @Autowired
    private MemberApplication memberApplication;

    @Value("${store.domain}")
    private String storeDomain;

    /**
     * 订单详情
     *
     * @param request
     * @param id      订单ID
     * @return com.
     */
    @GetMapping("/detail")
    @ResponseBody
    public Result detail(HttpServletRequest request, @RequestParam long id) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            Order order = queryChannelService.findOne(QOrder.order.id.eq(id).and(QOrder.order.member.eq(member)), Order.class);

            for (OrderDetail detail : order.getDetails()) {
                detail.setDefaultImage(storeDomain + "/uploads/" + detail.getDefaultImage());
                detail.setGoodsId(detail.getSku().getGoods().getId());
            }

            if (order.getIsAfterSale() == 1) {
                order.setOrderAfterSaleId(queryChannelService.findOne(QOrderAfterSale.orderAfterSale.order.id.eq(order.getId()), OrderAfterSale.class).getId());
            }

            order.setCurrentTime(new Timestamp(System.currentTimeMillis()));

            order.setMerchantInfo(ImmutableMap.of("id", order.getMerchant().getId(), "shopName", order.getMerchant().getShopName()));

            return result.ok().inject(order);

        } catch (Exception e) {
            logger.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 确认收货
     */
    @PutMapping("/receipt")
    @ResponseBody
    public Result receipt(HttpServletRequest request, @RequestBody OrderDTO params) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            Order order = queryChannelService.findOne(QOrder.order.id.eq(params.getId()).and(QOrder.order.member.eq(member)), Order.class);
            orderApplication.purchaseReceipt(order);

            return result.ok().inject(order);

        } catch (Exception e) {
            logger.error("[确认收货异常]", e);
            return result.fail().setMsg("确认收货异常");
        }
    }

    /**
     * 取消订单
     */
    @PutMapping("/cancel")
    @ResponseBody
    public Result cancel(HttpServletRequest request, @RequestBody OrderDTO params) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            Order order = queryChannelService.findOne(QOrder.order.id.eq(params.getId()).and(QOrder.order.member.eq(member)), Order.class);
            if (null == order) {
                return result.fail().setMsg("非法操作");
            }
            orderApplication.cancel(order, params.getNote());

            return result.ok();

        } catch (Exception e) {
            logger.error("[取消订单异常]", e);
            return result.fail().setMsg("取消订单异常");
        }
    }


    /**
     * 取消原因
     *
     * @param request
     * @return
     */
    @GetMapping("/cancelCause")
    @ResponseBody
    public Result cancelCause(HttpServletRequest request) {
        Result result = new Result();
        try {

            List<CancelCause> cancelCauses = queryChannelService.findAll(QCancelCause.cancelCause.status.eq(1), CancelCause.class);

            return result.ok().inject(cancelCauses);

        } catch (Exception e) {
            logger.error("[获取取消原因列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 全部订单列表
     *
     * @param request
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/list")
    @ResponseBody
    public Result list(HttpServletRequest request, @RequestParam(defaultValue = "1") int pageNo, @RequestParam(defaultValue = "20") int pageSize, @RequestParam(defaultValue = "0") int status) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageNo).setPageSize(pageSize);
            Map<String, Object> params = Maps.newHashMap();
            params.put("id", member.getId());

            String hql = builderHql("select o from Order o where o.isSupplier=1 and o.member.id = :id ", params, status);
            QueryPage<Order> page = queryChannelService.findPage(hql, pageRequest.setParams(params), Order.class);

            for (Order order : page.getResult()) {

                if (order.getIsAfterSale() == 1) {
                    order.setOrderAfterSaleId(queryChannelService.findOne(QOrderAfterSale.orderAfterSale.order.id.eq(order.getId()), OrderAfterSale.class).getId());
                }

                for (OrderDetail detail : order.getDetails()) {
                    detail.setDefaultImage(storeDomain + "/uploads/" + detail.getDefaultImage());
                    detail.setGoodsId(detail.getSku().getGoods().getId());

                }

            }

            return result.ok().inject(ImmutableMap.of("page", page));

        } catch (Exception e) {
            logger.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 查看发货记录
     *
     * @param request
     * @param id
     * @return
     */
    @GetMapping("/deliverys")
    @ResponseBody
    public Result deliverys(HttpServletRequest request, @RequestParam long id) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            List<SupplierOrderDelivery> deliveries = queryChannelService.findAll(QSupplierOrderDelivery.supplierOrderDelivery.order.id.eq(id), SupplierOrderDelivery.class);

            return result.ok().inject(deliveries);

        } catch (Exception e) {
            logger.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 查看快递物流信息
     *
     * @param request
     * @param id
     * @return
     */
    @GetMapping("/deliveryRecords")
    @ResponseBody
    public Result deliveryRecords(HttpServletRequest request, @RequestParam long id) {
        Result result = new Result();
        try {

            SupplierOrderDelivery delivery = queryChannelService.findOne(QSupplierOrderDelivery.supplierOrderDelivery.id.eq(id), SupplierOrderDelivery.class);

            JSONObject item = new JSONObject();
            item.put("com", delivery.getExpressCompanyCode());
            item.put("num", delivery.getExpressNo());
            String param = item.toString();
            String customer = "54C47E7E32F6C71A37CA09D73E953119";
            String key = "MhDOdUjx726";
            String sign = MD5HashUtils.MD5(param + key + customer).toUpperCase();

            List<NameValuePair> postparams = Lists.newArrayList();
            postparams.add(new BasicNameValuePair("param", param));
            postparams.add(new BasicNameValuePair("sign", sign));
            postparams.add(new BasicNameValuePair("customer", customer));

            String message = HttpRequests.postEntity("https://poll.kuaidi100.com/poll/query.do", postparams);

            JSONObject object = JSONObject.fromObject(message);
            Map<String, Object> data2 = Maps.newHashMap();
            data2.put("company", delivery.getExpressCompany());
            data2.put("no", delivery.getExpressNo());
            if ("ok".equals(object.getString("message"))) {
                String data = object.getString("data");
                JSONArray logisticData = JSONArray.fromObject(data);
                List<Map<String, Object>> mapListJson = (List) logisticData;

                data2.put("data", mapListJson);
                return result.ok().inject(data2);
            } else {
                return result.ok().setMsg("暂无查询结果，请稍后再查").inject(data2);
            }

        } catch (Exception e) {
            logger.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    /**
     * 查看快递物流信息
     *
     * @param request
     * @param id
     * @return
     */
    @GetMapping("/orderDeliveryRecords")
    @ResponseBody
    public Result orderDeliveryRecords(HttpServletRequest request, @RequestParam long id) {
        Result result = new Result();
        try {

            Order order = queryChannelService.findOne(QOrder.order.id.eq(id), Order.class);

            JSONObject item = new JSONObject();
            item.put("com", order.getExpressCode());
            item.put("num", order.getExpressesNo());
            String param = item.toString();
            String customer = "54C47E7E32F6C71A37CA09D73E953119";
            String key = "MhDOdUjx726";
            String sign = MD5HashUtils.MD5(param + key + customer).toUpperCase();

            List<NameValuePair> postparams = Lists.newArrayList();
            postparams.add(new BasicNameValuePair("param", param));
            postparams.add(new BasicNameValuePair("sign", sign));
            postparams.add(new BasicNameValuePair("customer", customer));

            String message = HttpRequests.postEntity("https://poll.kuaidi100.com/poll/query.do", postparams);

            JSONObject object = JSONObject.fromObject(message);
            Map<String, Object> data2 = Maps.newHashMap();
            data2.put("company", order.getExpressCompany());
            data2.put("no", order.getExpressesNo());
            if ("ok".equals(object.getString("message"))) {
                String data = object.getString("data");
                JSONArray logisticData = JSONArray.fromObject(data);
                List<Map<String, Object>> mapListJson = (List) logisticData;

                data2.put("data", mapListJson);
                return result.ok().inject(data2);
            } else {
                return result.ok().setMsg("暂无查询结果，请稍后再查").inject(data2);
            }

        } catch (Exception e) {
            logger.error("[订单列表异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }

    private String builderHql(String hql, Map<String, Object> params, int status) {
        if (status > 0) {

            if (status == 3) {
                hql += " and o.status in (3, 10) ";
            } else {
                hql += " and o.status = :status ";
                params.put("status", status);
            }

        }

        hql += " order by o.createTime desc ";

        return hql;
    }


    /**
     * 提交订单
     */
    @RequestMapping(value = "/submit", method = RequestMethod.POST)
    @ResponseBody
    public Result submit(HttpServletRequest request, @RequestBody OrderDTO params) {
        Result result = new Result();
        try {

            WebUser member = queryChannelService.findOne(QWebUser.webUser.eq(Securitys.user(request)), WebUser.class);

            if (Strings.isNullOrEmpty(member.getMobile())) {
                return result.fail().setMsg("请先绑定手机号码");
            }

            if (params.getDetails().isEmpty()) {
                return result.fail().setMsg("此订单不支持购买");
            }


            List<Order> orders = orderApplication.submitOfSupplier(member, params);

            double amount = 0;
            for (Order order : orders) {
                amount = ArithUtils.add(amount, order.getPrice());
            }

            return result.ok().inject(ImmutableMap.of("orders", orders, "amount", amount, "time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));

        } catch (Exception e) {

            if (e instanceof InterfaceException) {
                return result.fail().setMsg(e.getMessage());
            }

            if (e instanceof IllegalStateException) {
                return result.fail().setMsg(e.getMessage());
            }

            logger.error("[提交订单异常]", e);
            return result.fail().setMsg("订单提交失败");
        }
    }

    /**
     * 钱包余额全量支付抵扣订单
     */
    @RequestMapping(value = "/blancePay", method = RequestMethod.POST)
    @ResponseBody
    public Result blancePay(HttpServletRequest request, @RequestBody SupplierOrderDTO orderParams) {
        Result result = new Result();
        try {

            WebUser member = Securitys.user(request);
            List<Long> ids = orderParams.getOrders().stream().map(OrderDTO::getId).collect(Collectors.toList());
            List<Order> orders = queryChannelService.findAll(QOrder.order.id.in(ids).and(QOrder.order.member.eq(member)), Order.class);

            for (Order order : orders) {
                if (order.getStatus() == 2) {
                    return result.fail().setMsg("非法操作");
                }
            }

            orderApplication.blanceFullPay(orders);
            return result.ok();

        } catch (Exception e) {
            if (e instanceof InterfaceException) {
                return result.fail().setMsg(e.getMessage());
            }
            logger.error("[提交订单异常]", e);
            return result.fail().setMsg("订单提交失败");
        }
    }


    /**
     * 线下转账支付
     */
    @RequestMapping(value = "/bankCardPay", method = RequestMethod.POST)
    @ResponseBody
    public Result bankCardPay(HttpServletRequest request, @RequestBody List<OrderDTO> params) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            List<Order> orders = queryChannelService.findAll(QOrder.order.id.in(params.stream().map(OrderDTO::getId).collect(Collectors.toList())).and(QOrder.order.member.eq(member)), Order.class);
            for (Order order : orders) {
                if (order.getStatus() == 2) {
                    return result.fail().setMsg("非法操作");
                }
            }
            for (OrderDTO param : params) {
                Order order = queryChannelService.findOne(QOrder.order.id.eq(param.getId()), Order.class);
                order.setBankCardPayNote(param.getBankCardPayNote());
                order.setBankCardPayPhoto(param.getBankCardPayPhoto());
                orderApplication.bankCardPay(order);
            }
            return result.ok();
        } catch (InterfaceException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            logger.error("[提交订单异常]", e);
            return result.fail().setMsg("订单提交失败");
        }
    }

    /**
     * 修改收货人，重新计算运费
     */
    @RequestMapping(value = "/totalFreightPrice", method = RequestMethod.PUT)
    @ResponseBody
    public Result totalFreightPrice(HttpServletRequest request, @RequestBody OrderPreviewDTO orderPreview) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            List<Long> ids = orderPreview.getCarts().stream().map(ShopCartDTO::getId).collect(Collectors.toList());

            Set<Long> merchantIds = new HashSet<>();
            List<ShoppingCart> shoppingCarts = queryChannelService.findAll(QShoppingCart.shoppingCart.member.eq(member).and(QShoppingCart.shoppingCart.id.in(ids)), ShoppingCart.class);
            for (ShoppingCart cart : shoppingCarts) {
                merchantIds.add(cart.getSku().getGoods().getMerchant().getId());
            }

            List<WebUser> merchants = queryChannelService.findAll(QWebUser.webUser.id.in(merchantIds), WebUser.class);
            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = Lists.newArrayList();
            for (WebUser merchant : merchants) {
                MerchantShoppingCartGoodsDTO merchantShoppingCartGoods = new MerchantShoppingCartGoodsDTO();
                merchantShoppingCartGoods.setMerchantId(merchant.getId());
                merchantShoppingCartGoods.setMerchantName(merchant.getShopName());

                int goodsCount = 0;
                double subtotalPrice = 0.0;

                List<ShoppingCart> carts = Lists.newArrayList();
                for (ShoppingCart cart : shoppingCarts) {
                    if (cart.getSku().getGoods().getMerchant().getId() == merchant.getId()) {
                        cart.setGoodsImage(storeDomain + "/uploads/" + cart.getGoodsImage());

                        goodsCount += cart.getQuantity();
                        subtotalPrice = ArithUtils.add(subtotalPrice, cart.getSubtotalPrice());

                        carts.add(cart);
                    }
                }

                merchantShoppingCartGoods.setGoodsCount(goodsCount);
                merchantShoppingCartGoods.setSubtotalPrice(subtotalPrice);

                merchantShoppingCartGoods.setGoodsList(carts);
                merchantGoodsList.add(merchantShoppingCartGoods);

            }


            DeliveryAddress deliveryAddress = new DeliveryAddress();
            deliveryAddress.setProvince(orderPreview.getProvince());
            deliveryAddress.setCity(orderPreview.getCity());

            return result.ok().inject(totalFreightPrice(deliveryAddress, merchantGoodsList));
        } catch (Exception e) {
            logger.error("[计算运费异常]", e);
            return result.fail().setMsg("计算运费失败");
        }
    }


    /**
     * 立即购买计算运费
     */
    @RequestMapping(value = "/buyTotalFreightPrice", method = RequestMethod.PUT)
    @ResponseBody
    public Result buyTotalFreightPrice(@RequestBody OrderPreviewDTO orderParam) {
        Result result = new Result();
        try {

            List<ShoppingCart> carts = Lists.newArrayList();
            MerchantShoppingCartGoodsDTO merchantShoppingCartGoods = new MerchantShoppingCartGoodsDTO();
            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = Lists.newArrayList();

            for (ShopCartDTO param : orderParam.getCarts()) {

                GoodsSku sku = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(param.getId()), GoodsSku.class);
                merchantShoppingCartGoods.setMerchantId(sku.getMerchant().getId());
                merchantShoppingCartGoods.setGoodsCount(param.getQuantity());

                ShoppingCart cart = new ShoppingCart();
                cart.setGoodsImage(storeDomain + "/uploads/" + sku.getGoods().getDefaultImage());
                cart.setGoodsName(sku.getGoods().getName());
                cart.setSkuNames(StringUtils.replace(sku.getSkuNames(), ",", " "));
                cart.setSku(sku);
                cart.setSubtotalPrice(ArithUtils.mul(goodsApplication.getSupplierLeverPrice(sku, param.getQuantity()), param.getQuantity()));
                cart.setQuantity(param.getQuantity());

                carts.add(cart);
            }


            merchantShoppingCartGoods.setGoodsList(carts);

            merchantGoodsList.add(merchantShoppingCartGoods);

            DeliveryAddress deliveryAddress = new DeliveryAddress();
            deliveryAddress.setProvince(orderParam.getProvince());
            deliveryAddress.setCity(orderParam.getCity());

            return result.ok().inject(totalFreightPrice(deliveryAddress, merchantGoodsList));
        } catch (Exception e) {
            logger.error("[计算运费异常]", e);
            return result.fail().setMsg("计算运费失败");
        }
    }

    /**
     * 去结算（订单预览）
     */
    @RequestMapping(value = "/preview", method = RequestMethod.POST)
    @ResponseBody
    public Result preview(HttpServletRequest request, @RequestBody List<ShopCartDTO> params) {
        Result result = new Result();

        try {

            WebUser member = Securitys.user(request);

            List<Long> ids = params.stream().map(ShopCartDTO::getId).collect(Collectors.toList());

            Set<Long> merchantIds = Sets.newHashSet();
            List<ShoppingCart> shoppingCarts = queryChannelService.findAll(QShoppingCart.shoppingCart.member.eq(member).and(QShoppingCart.shoppingCart.id.in(ids)), ShoppingCart.class);
            for (ShoppingCart cart : shoppingCarts) {
                merchantIds.add(cart.getSku().getGoods().getMerchant().getId());
            }

            List<WebUser> merchants = queryChannelService.findAll(QWebUser.webUser.id.in(merchantIds), WebUser.class);

            DeliveryAddress deliveryAddress = queryChannelService.findOne(QDeliveryAddress.deliveryAddress.member.eq(member).and(QDeliveryAddress.deliveryAddress.defaultAddress.isTrue()), DeliveryAddress.class);

            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = Lists.newArrayList();
            for (WebUser merchant : merchants) {
                MerchantShoppingCartGoodsDTO merchantItem = new MerchantShoppingCartGoodsDTO();
                merchantItem.setMerchantId(merchant.getId());
                merchantItem.setMerchantName(merchant.getShopName());

                int goodsCount = 0;
                double subtotalPrice = 0.0;

                List<ShoppingCart> carts = new ArrayList<>();
                for (ShoppingCart cart : shoppingCarts) {
                    if (cart.getSku().getGoods().getMerchant().getId() == merchant.getId()) {
                        cart.setGoodsImage(storeDomain + "/uploads/" + cart.getGoodsImage());
                        cart.setGoodsId(cart.getSku().getGoods().getId());
                        goodsCount += cart.getQuantity();
                        subtotalPrice = ArithUtils.add(subtotalPrice, cart.getSubtotalPrice());
                        cart.setGoodsUnit(cart.getSku().getGoods().getUnit());
                        if (cart.getSku().getGoods().getUnit().getId() == cart.getUnit().getId()) {
                            cart.setUnitValue(1);
                            cart.setUnitQuantity(cart.getQuantity());
                        } else if (cart.getSku().getGoods().getAffiliatedUnit() != null && cart.getSku().getGoods().getAffiliatedUnit().getId() == cart.getUnit().getId()) {
                            cart.setUnitValue(cart.getSku().getGoods().getAffiliatedUnitValue());
                            cart.setUnitQuantity(new Double(ArithUtils.div(cart.getQuantity(), cart.getSku().getGoods().getAffiliatedUnitValue(), 2)).intValue());

                        } else if (cart.getSku().getGoods().getUltimateUnit() != null && cart.getSku().getGoods().getUltimateUnit().getId() == cart.getUnit().getId()) {
                            cart.setUnitValue(cart.getSku().getGoods().getUltimateUnitValue());
                            cart.setUnitQuantity(new Double(ArithUtils.div(cart.getQuantity(), cart.getSku().getGoods().getUltimateUnitValue(), 2)).intValue());
                        }
                        carts.add(cart);
                    }
                }


                merchantItem.setGoodsCount(goodsCount);
                merchantItem.setSubtotalPrice(subtotalPrice);
                merchantItem.setGoodsList(carts);
                merchantItem.setWarehouseAddress(merchant.getWarehouseAddress());

                merchantGoodsList.add(merchantItem);

            }

            Map<String, Object> data = Maps.newHashMap();
            data.put("deliveryInfo", deliveryAddress);

            if (null == deliveryAddress) {
                data.put("merchants", merchantGoodsList);
            } else {
                data.put("merchants", totalFreightPrice(deliveryAddress, merchantGoodsList));
            }

            return result.ok().inject(data);

        } catch (Exception e) {
            logger.error("[订单预览异常]", e);
            return result.fail().setMsg("订单预览异常");
        }

    }


    /**
     * 立即购买
     */
    @RequestMapping(value = "/buy", method = RequestMethod.POST)
    @ResponseBody
    public Result buy(HttpServletRequest request, @RequestBody List<ShopCartDTO> paramses) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);
            List<MerchantShoppingCartGoodsDTO> merchantGoodsList = Lists.newArrayList();

            DeliveryAddress deliveryAddress = queryChannelService.findOne(QDeliveryAddress.deliveryAddress.member.eq(member).and(QDeliveryAddress.deliveryAddress.defaultAddress.isTrue()), DeliveryAddress.class);
            WebUser merchant = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(paramses.get(0).getId()), GoodsSku.class).getMerchant();

            MerchantShoppingCartGoodsDTO merchantItem = new MerchantShoppingCartGoodsDTO();
            merchantItem.setMerchantId(merchant.getId());
            merchantItem.setMerchantName(merchant.getShopName());

            merchantItem.setWarehouseAddress(merchant.getWarehouseAddress());

            int quantity = 0;
            double price = 0;

            for (ShopCartDTO params : paramses) {
                GoodsSku sku = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(params.getId()), GoodsSku.class);


                List<ShoppingCart> carts = Lists.newArrayList();

                ShoppingCart cart = new ShoppingCart();
                cart.setGoodsImage(storeDomain + "/uploads/" + sku.getGoods().getDefaultImage());
                cart.setGoodsId(sku.getGoods().getId());
                cart.setGoodsName(sku.getGoods().getName());
                cart.setSkuNames(StringUtils.replace(sku.getSkuNames(), ",", " "));
                cart.setSku(sku);
                cart.setGoodsUnit(sku.getGoods().getUnit());

                GoodsUnit unit = queryChannelService.findOne(QGoodsUnit.goodsUnit.id.eq(params.getUnitId()), GoodsUnit.class);
                cart.setUnit(unit);

                cart.setSubtotalPrice(ArithUtils.mul(goodsApplication.getSupplierLeverPrice(sku, params.getQuantity()), params.getQuantity()));
                cart.setQuantity(params.getQuantity());

                if (sku.getGoods().getUnit().getId() == cart.getUnit().getId()) {
                    cart.setUnitValue(1);
                    cart.setUnitQuantity(params.getQuantity());
                } else if (sku.getGoods().getAffiliatedUnit() != null && sku.getGoods().getAffiliatedUnit().getId() == cart.getUnit().getId()) {
                    cart.setUnitValue(sku.getGoods().getAffiliatedUnitValue());
                    cart.setUnitQuantity(new Double(ArithUtils.div(cart.getQuantity(), sku.getGoods().getAffiliatedUnitValue(), 2)).intValue());

                } else if (sku.getGoods().getUltimateUnit() != null && sku.getGoods().getUltimateUnit().getId() == cart.getUnit().getId()) {
                    cart.setUnitValue(sku.getGoods().getUltimateUnitValue());
                    cart.setUnitQuantity(new Double(ArithUtils.div(cart.getQuantity(), sku.getGoods().getUltimateUnitValue(), 2)).intValue());
                }

                quantity += params.getQuantity();

                price = ArithUtils.add(price, ArithUtils.mul(goodsApplication.getSupplierLeverPrice(sku, params.getQuantity()), params.getQuantity()));

                carts.add(cart);

                merchantItem.getGoodsList().addAll(carts);
            }

            merchantItem.setGoodsCount(quantity);
            merchantItem.setSubtotalPrice(price);

            merchantGoodsList.add(merchantItem);

            Map<String, Object> data = new HashMap<>();
            data.put("deliveryInfo", deliveryAddress);

            if (null == deliveryAddress) {
                data.put("merchants", merchantGoodsList);
            } else {
                data.put("merchants", totalFreightPrice(deliveryAddress, merchantGoodsList));
            }


            return result.ok().inject(data);

        } catch (Exception e) {
            logger.error("[订单预览异常]", e);
            return result.fail().setMsg("订单预览异常");
        }

    }


    /**
     * 计算运费
     */
    private List<MerchantShoppingCartGoodsDTO> totalFreightPrice(DeliveryAddress deliveryAddress, List<MerchantShoppingCartGoodsDTO> goodsList) {

        for (MerchantShoppingCartGoodsDTO item : goodsList) {

            WebUser merchant = queryChannelService.findOne(QWebUser.webUser.id.eq(item.getMerchantId()), WebUser.class);
            double freightPrice = 0;

            List<ShoppingCart> result = Lists.newArrayList();
            Map<Long, Integer> nummbers = Maps.newHashMap();
            Map<Long, Double> grams = Maps.newHashMap();

            for (ShoppingCart shoppingCart : item.getGoodsList()) {
                if (nummbers.containsKey(shoppingCart.getSku().getGoods().getId())) {
                    int quantity = nummbers.get(shoppingCart.getSku().getGoods().getId());
                    nummbers.put(shoppingCart.getSku().getGoods().getId(), quantity + shoppingCart.getQuantity());

                } else {

                    nummbers.put(shoppingCart.getSku().getGoods().getId(), shoppingCart.getQuantity());
                    grams.put(shoppingCart.getSku().getGoods().getId(), shoppingCart.getSku().getGoods().getGram());
                    result.add(shoppingCart);
                }
            }

            for (ShoppingCart shoppingCart : result) {
                int quantity = nummbers.get(shoppingCart.getSku().getGoods().getId());
                shoppingCart.setCount(quantity);

                double gram = grams.get(shoppingCart.getSku().getGoods().getId());
                shoppingCart.getSku().getGoods().setGram(gram);
            }


            for (ShoppingCart shoppingCart : result) {


                Goods goods = shoppingCart.getSku().getGoods();

                if (shoppingCart.getCount() != 0) {


                    //运费模板
                    if (goods.getSupplierPostageType() == 1) {

                        MerchantFreight freight = queryChannelService.findOne(QMerchantFreight.merchantFreight.city.eq(deliveryAddress.getCity()).and(QMerchantFreight.merchantFreight.merchant.eq(merchant).and(QMerchantFreight.merchantFreight.template.id.eq(goods.getSupplierFreightTemplate().getId()))), MerchantFreight.class);

                        MerchantFreightTemplate template = queryChannelService.findOne(QMerchantFreightTemplate.merchantFreightTemplate.id.eq(goods.getSupplierFreightTemplate().getId()), MerchantFreightTemplate.class);

                        //按重量
                        if (template.getType() == 1) {

                            if (null != freight) {   //拿到了模板内设置的区域运费

                                double gram = ArithUtils.mul(goods.getGram(), shoppingCart.getCount());//总重量

                                if (gram <= freight.getFirstWeight()) {
                                    freightPrice += freight.getFirstWeightAmount();
                                } else {
                                    double fistWeightAmount = freight.getFirstWeightAmount();
                                    double weight = ArithUtils.sub(gram, freight.getFirstWeight());

                                    if (weight < freight.getOtherWeight()) {
                                        freightPrice += ArithUtils.add(fistWeightAmount, freight.getOtherWeightAmount());
                                    } else {
                                        freightPrice += ArithUtils.add(fistWeightAmount, ArithUtils.mul(Math.ceil(ArithUtils.div(weight, freight.getOtherWeight(), 2)), freight.getOtherWeightAmount()));
                                    }
                                }

                            } else {

                                double gram = ArithUtils.mul(goods.getGram(), shoppingCart.getCount());//总重量

                                if (gram <= template.getDefaultWeight()) {
                                    freightPrice += template.getDefaultWeightAmount();
                                } else {

                                    double fistWeightAmount = template.getDefaultWeightAmount();
                                    double weight = ArithUtils.sub(gram, template.getDefaultWeight());

                                    if (weight < template.getDefaultAddWeight()) {
                                        freightPrice += ArithUtils.add(fistWeightAmount, template.getDefaultAddWeightAmount());
                                    } else {
                                        freightPrice += ArithUtils.add(fistWeightAmount, ArithUtils.mul(Math.ceil(ArithUtils.div(weight, template.getDefaultAddWeight(), 2)), template.getDefaultAddWeightAmount()));
                                    }
                                }

                            }

                        }

                        //按件
                        if (template.getType() == 2) {

                            if (null != freight) {

                                if (shoppingCart.getCount() <= freight.getFirstPiece()) {
                                    freightPrice += freight.getFirstPieceAmount();
                                } else {
                                    freightPrice += ArithUtils.add(freight.getFirstPieceAmount(), ArithUtils.mul(ArithUtils.sub(shoppingCart.getCount(), freight.getFirstPiece()), freight.getOtherPieceAmount()));
                                }

                            } else {

                                if (shoppingCart.getCount() <= template.getDefaultPiece()) {
                                    freightPrice += template.getDefaultPieceAmount();
                                } else {
                                    freightPrice += ArithUtils.add(template.getDefaultPieceAmount(), ArithUtils.mul(ArithUtils.sub(shoppingCart.getCount(), template.getDefaultPiece()), template.getDefaultAddPieceAmount()));
                                }

                            }

                        }

                    } else if (goods.getSupplierPostageType() == 2) {      //包邮
                        freightPrice += ArithUtils.add(freightPrice, 0);
                    } else if (goods.getSupplierPostageType() == 3) {        //指定运费
                        freightPrice += ArithUtils.add(freightPrice, ArithUtils.mul(goods.getSupplierPostage(), shoppingCart.getCount()));
                    }
                }
            }
            item.setFreightPrice(freightPrice);
        }

        return goodsList;
    }


    /**
     * 统计订单数量
     */
    @GetMapping("/count")
    @ResponseBody
    public Result count(HttpServletRequest request) {
        Result result = new Result();
        try {
            WebUser member = Securitys.user(request);

            int count1 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 1", ImmutableMap.of("mid", member.getId()));
            int count2 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 2", ImmutableMap.of("mid", member.getId()));
            int count3 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 3", ImmutableMap.of("mid", member.getId()));
            int count4 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and status = 4", ImmutableMap.of("mid", member.getId()));
            int count5 = queryChannelService.selectCount("select count(*) from mall_order where member_id = :mid and isAfterSale = 1", ImmutableMap.of("mid", member.getId()));

            return result.ok().inject(ImmutableMap.of("count1", count1, "count2", count2, "count3", count3, "count4", count4, "count5", count5));

        } catch (Exception e) {
            logger.error("[订单统计异常]", e);
            return result.fail().setMsg("网络请求异常");
        }
    }
}
